package org.plants.algo;

import java.util.Random;
import java.util.Scanner;

public abstract class Algorithm {
	
	private static void printPool (Character[][] pool, int poolSize) {
		for(int i = 0; i < poolSize; i++) {
			for(int j = 0; j < poolSize; j++) {
				System.out.print(pool[i][j]);
			}
			System.out.println();
		}
	}
	
	private static int getSuitables(int plantsNumber, int poolSize, int lifeDuration) {
		int result = 0;
		if (BestCoverOscilator.isSuitableFigure(plantsNumber, poolSize, lifeDuration))
			result++;
		if (CollidingGliders.isSuitableFigure(plantsNumber, poolSize, lifeDuration))
			result++;
		if (Explosion.isSuitableFigure(plantsNumber, poolSize, lifeDuration))
			result++;
		if (GlidersFilling.isSuitableFigure(plantsNumber, poolSize, lifeDuration))
			result++;
		if (OscilatorGrande.isSuitableFigure(plantsNumber, poolSize, lifeDuration))
			result++;
		if (PufferTrain.isSuitableFigure(plantsNumber, poolSize, lifeDuration))
			result++;
		if (SimpleLine.isSuitableFigure(plantsNumber, poolSize, lifeDuration))
			result++;
		if (RandomFilling.isSuitableFigure(plantsNumber, poolSize, lifeDuration))
			result++;
		if (DefaultFilling.isSuitableFigure(plantsNumber, poolSize, lifeDuration))
			result++;
		
		return result;
	}
	
	private static Character[][] duplicatePool(int poolSize, Character[][] pool) {
		Character[][] result = new Character[poolSize][poolSize];
		
		for (int i = 0; i < poolSize; i++) 
			for(int j = 0; j < poolSize; j++) 
				result[i][j] = pool[i][j];
		
		return result;
	}
	
	private static void drawIfSuitable(String figureName, int plantsNumber, int poolSize, int lifeDuration, Character[][] pool) {
		switch (figureName) {
		case "BestCoverOscilator" :
			if (BestCoverOscilator.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
				Character[][] tempPool = duplicatePool(poolSize, pool);
				BestCoverOscilator.fillPool(tempPool, plantsNumber, poolSize);
				//System.out.println(BestCoverOscilator.getName());
				printPool(tempPool, poolSize);
			}
			break;
		case "CollidingGliders" :
			if (CollidingGliders.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
				Character[][] tempPool = duplicatePool(poolSize, pool);
				CollidingGliders.fillPool(tempPool, plantsNumber, poolSize);
				//System.out.println(CollidingGliders.getName());
				printPool(tempPool, poolSize);
			}
			break;
		case "Explosion" :
			if (Explosion.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
				Character[][] tempPool = duplicatePool(poolSize, pool);
				Explosion.fillPool(tempPool, plantsNumber, poolSize);
				//System.out.println(Explosion.getName());
				printPool(tempPool, poolSize);
			}
			break;
		case "GlidersFilling" :
			if (GlidersFilling.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
				Character[][] tempPool = duplicatePool(poolSize, pool);
				GlidersFilling.fillPool(tempPool, plantsNumber, poolSize);
				//System.out.println(GlidersFilling.getName());
				printPool(tempPool, poolSize);
			}
			break;
		case "OscilatorGrande" :
			if (OscilatorGrande.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
				Character[][] tempPool = duplicatePool(poolSize, pool);
				OscilatorGrande.fillPool(tempPool, plantsNumber, poolSize);
				//System.out.println(OscilatorGrande.getName());
				printPool(tempPool, poolSize);
			}
			break;
		case "PufferTrain" :
			if (PufferTrain.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
				Character[][] tempPool = duplicatePool(poolSize, pool);
				PufferTrain.fillPool(tempPool, plantsNumber, poolSize);
				//System.out.println(PufferTrain.getName());
				printPool(tempPool, poolSize);
			}
			break;
		case "SimpleLine" :
			if (SimpleLine.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
				Character[][] tempPool = duplicatePool(poolSize, pool);
				SimpleLine.fillPool(tempPool, plantsNumber, poolSize);
				//System.out.println(SimpleLine.getName());
				printPool(tempPool, poolSize);
			}
			break;
		case "RandomFilling" :
			if (RandomFilling.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
				Character[][] tempPool = duplicatePool(poolSize, pool);
				RandomFilling.fillPool(tempPool, plantsNumber, poolSize);
				//System.out.println(RandomFilling.getName());
				printPool(tempPool, poolSize);
			}
			break;
		case "DefaultFilling" :
			if (DefaultFilling.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
				Character[][] tempPool = duplicatePool(poolSize, pool);
				DefaultFilling.fillPool(tempPool, plantsNumber, poolSize);
				//System.out.println(DefaultFilling.getName());
				printPool(tempPool, poolSize);
			}
			break;
		default :
			break;
		}
	}
	private static String chooseFigure(int plantsNumber, int poolSize, int lifeDuration) {
		if (SimpleLine.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
			return SimpleLine.getName();
		} else {
			if (BestCoverOscilator.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
				return BestCoverOscilator.getName();
			} else {
				if (Explosion.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
					return Explosion.getName();
				} else {
					if (PufferTrain.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
						return PufferTrain.getName();
					} else {
						if (OscilatorGrande.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
							return OscilatorGrande.getName();
						} else {
							if (GlidersFilling.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
								return GlidersFilling.getName();
							} else {
								if (CollidingGliders.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
									return CollidingGliders.getName();
								} else {
									if (RandomFilling.isSuitableFigure(plantsNumber, poolSize, lifeDuration)) {
										return RandomFilling.getName();
									}
								}
							}
						}
					}
				}
			}
		}
		return DefaultFilling.getName();
	}

	
	public static void main (String args[]) {
		int lifeDuration;
		int plantsNumber;
		int poolSize;
		
		
		Scanner scan = new Scanner(System.in);
		
		do {
			lifeDuration = scan.nextInt();
			plantsNumber = scan.nextInt();
			poolSize = scan.nextInt();
			scan.nextLine();
			
			Character[][] pool = new Character[poolSize][poolSize];
			
			
			//Fill the Matrix
			for (int i =0; i < poolSize; i++) {
				String inputLine = scan.nextLine();
				for (int j = 0; j < poolSize; j++) {
					pool[i][j] = inputLine.charAt(j);
				}
			}
			
			//System.out.println(lifeDuration);
			//System.out.println(plantsNumber);
			//System.out.println(poolSize);
			//printPool(pool, poolSize);
			
			//System.out.println(getSuitables(plantsNumber, poolSize, lifeDuration));
			
			String myChoise = chooseFigure(plantsNumber, poolSize, lifeDuration);
			
			drawIfSuitable(myChoise, plantsNumber, poolSize, lifeDuration, pool);
			/*
			drawIfSuitable(BestCoverOscilator.getName(), plantsNumber, poolSize, lifeDuration, pool);
			drawIfSuitable(CollidingGliders.getName(), plantsNumber, poolSize, lifeDuration, pool);
			drawIfSuitable(Explosion.getName(), plantsNumber, poolSize, lifeDuration, pool);
			//drawIfSuitable(GlidersFilling.getName(), plantsNumber, poolSize, lifeDuration, pool);
			drawIfSuitable(OscilatorGrande.getName(), plantsNumber, poolSize, lifeDuration, pool);
			drawIfSuitable(PufferTrain.getName(), plantsNumber, poolSize, lifeDuration, pool);
			drawIfSuitable(SimpleLine.getName(), plantsNumber, poolSize, lifeDuration, pool);
			drawIfSuitable(RandomFilling.getName(), plantsNumber, poolSize, lifeDuration, pool);
			drawIfSuitable(DefaultFilling.getName(), plantsNumber, poolSize, lifeDuration, pool);
			*/
		} while(scan.hasNext());
		
	}
}
